package com.hcc.flow.server.service.sys;

import java.util.Arrays;
import java.util.Date;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.hcc.flow.server.common.constant.Constant;
import com.hcc.flow.server.common.constant.RedisKeyConstant;
import com.hcc.flow.server.common.enums.IfStatusType;
import com.hcc.flow.server.common.enums.QueryDataType;
import com.hcc.flow.server.common.model.ApiResult;
import com.hcc.flow.server.common.utils.PinyinUtils;
import com.hcc.flow.server.common.utils.StringUtilsV2;
import com.hcc.flow.server.common.utils.TokenUtil;
import com.hcc.flow.server.common.where.PublicPara;
import com.hcc.flow.server.dao.sys.OrgDao;
import com.hcc.flow.server.dao.sys.PermissionDao;
import com.hcc.flow.server.dao.sys.RoleDao;
import com.hcc.flow.server.dao.sys.UserDao;
import com.hcc.flow.server.dto.sys.ChangePasswordDto;
import com.hcc.flow.server.dto.sys.UserDto;
import com.hcc.flow.server.model.common.LoginUser;
import com.hcc.flow.server.model.sys.Org;
import com.hcc.flow.server.model.sys.SysUser;
import com.hcc.flow.server.utils.CheckIdUtil;
import com.hcc.flow.server.utils.UserUtil;

@Service
public class UserService {

	private static final Logger log = LoggerFactory.getLogger("adminLogger");
	/**
	 * token过期秒数
	 */
	@Value("${token.expire.seconds}")
	private Long expireSeconds;
	
	@Autowired
	private UserDao userDao;
	@Autowired
	private BCryptPasswordEncoder passwordEncoder;
	@Autowired
	private OrgDao orgDao;
	@Autowired
	private RoleDao roleDao;
	@Autowired
	private PermissionDao permissionDao;
	@Autowired
	private TokenService tokenService;
	
	@Transactional
	public String saveUser(UserDto userDto) {
		SysUser loginUser = UserUtil.getLoginUserNullSys();
		SysUser user = userDto;
		user.setCreateUserId(loginUser.getUserId());
		user.setCreateOrgId(loginUser.getOrgId());
		String password = user.getPassword();
		if (StringUtilsV2.isBlank(password)) {
			user.setPassword(passwordEncoder.encode(Constant.DEFALUT_USER_PASSWORD));
			//password = PasswordUtil.randomPassword();
		}
		user.setPassword(passwordEncoder.encode(password));
		if(StringUtilsV2.isNotBlank(userDto.getOrgName())){
			Org org = orgDao.getByName(userDto.getOrgName());
			if(org == null){
				org = new Org();
				org.setParentId(loginUser.getOrgId());
				org.setLevel(2);
				org.setOrgTypeId(Constant.ORG_GYS_TYPE_ID.toString());
				org.setOrgName(userDto.getOrgName());
				org.setOrgCode(PinyinUtils.getLowerCase(userDto.getOrgName(), true));
				org.setCreateUserId(loginUser.getUserId());
				org.setCreateOrgId(loginUser.getOrgId());
				org.setCreateTime(new Date());
				orgDao.save(org);
			}else {
				if("D".equals(org.getOrgStatus())){
					org.setOrgStatus("C");
				}
				orgDao.updateStatus(Arrays.asList(org.getOrgId()), "C");
			}
			user.setOrgId(org.getOrgId());
		}
		userDao.save(user);
		saveUserRoles(user.getUserId(), userDto.getRoleIds());
		log.debug("新增用户{}", user.getUserAcct());
		return password;
	}

	private void saveUserRoles(String userId, List<String> roleIds) {
		if (roleIds != null) {
			userDao.deleteUserRole(userId);
			if (!CollectionUtils.isEmpty(roleIds)) {
				userDao.saveUserRoles(userId, roleIds);
			}
		}
	}

	
	public SysUser getUser(String username) {
		return userDao.getUser(username);
	}
	
	
	public String getUserOrgId(String userId) {
		String orgId = null;
		SysUser user = userDao.getUserById(userId);
		if(user != null) {
			return user.getOrgId();
		}
		return orgId;
	}

	
	public ApiResult<?> changePassword(ChangePasswordDto dto) {
		String userId = UserUtil.getLoginUser().getUserId();
		ApiResult<?> checkAr = CheckIdUtil.checkId(Arrays.asList("1","10"), userId);
		if(!checkAr.isSuccess()){
			return checkAr;
		}
		String oldPassword = dto.getOldPassword();
		String newPassword = dto.getNewPassword();
		SysUser u = userDao.getUserById(userId);
		if (u == null) {
			return ApiResult.error("用户不存在");
		}
		if (!passwordEncoder.matches(oldPassword, u.getPassword())) {
			return ApiResult.error("旧密码错误");
		}
		if (StringUtilsV2.isBlank(newPassword)) {
			return ApiResult.error("新密码不能为空");
		}
		if (newPassword.length() < 6) {
			return ApiResult.error("新密码长度不能小于6位");
		}
		userDao.changePassword(userId,userId, passwordEncoder.encode(newPassword),IfStatusType.N.getCode(),dto.getHeadImgUrl());
		log.debug("修改{}的密码", u.getUserAcct());
		return ApiResult.ok();
	}

	
	@Transactional
	public SysUser updateUser(UserDto userDto) {
		LoginUser loginUser = UserUtil.getLoginUser();
		if (StringUtilsV2.isNotBlank(userDto.getPassword())) {
			userDto.setPassword(passwordEncoder.encode(userDto.getPassword()));
			userDto.setIsEditPassword(IfStatusType.N.getCode());
			userDto.setLastEditPasswordTime(new Date());
		}
		userDto.setUpdateUserId(loginUser.getUserId());
		userDao.update(userDto);
		saveUserRoles(userDto.getUserId(), userDto.getRoleIds());
		if(loginUser.getUserId().equals(userDto.getUserId()))
			tokenService.refresh(loginUser,true,TokenUtil.getSysId(null));
		return userDto;
	}

	
	public ApiResult<?> changePasswordReset(String userId, String password) {
		LoginUser user = UserUtil.getLoginUser();
		userDao.changePassword(user.getUserId(),userId, passwordEncoder.encode(password),IfStatusType.Y.getCode(),user.getHeadImgUrl());
		return ApiResult.data(password);
	}

	
	public SysUser getUserPhone(String phone) {
		// TODO Auto-generated method stub
		return userDao.getUserByPhone(phone);
	}
	
	/**
	 * 根据机构id查询其下子机构ids,若传了机构类型id则只返回指定类型的子机构ids
	 */
	public String getChildOrgIdsByOrgId(String orgId) {
		if(StringUtilsV2.isBlank(orgId)){
			orgId = UserUtil.getLoginUser().getOrgId();
		}
		String childOrgIdsStr = userDao.getChildOrgIdsByOrgId(orgId);
		
		if(StringUtilsV2.isBlank(childOrgIdsStr)) {
			return orgId;
		}
		return childOrgIdsStr;
	}

	public List<String> getListUserIdsByOrgId(String orgId) {
		String childOrgIds = getChildOrgIdsByOrgId(orgId);
		return userDao.listUserIdsByOrgIds(childOrgIds);
	}
	
	public List<String> getListUserIdsByRoleIdsNoChild(String roleIds) {
		if(StringUtilsV2.isBlank(roleIds)){
			LoginUser loginUser = UserUtil.getLoginUser();
			roleIds = loginUser.getRoldIds();
			if(StringUtilsV2.isBlank(roleIds)){
				roleIds = roleDao.getRoleIdsByUserId(loginUser.getUserId());
			}
		}
		Object childUserIds = RedisServer.getCacheValue(null,RedisKeyConstant.KEY_USER_IDS_BY_ROLE_IDS+roleIds);
		if(childUserIds == null){
			String childUserIdsStr = userDao.getUserIdsByRoleIdsNoChild(roleIds);
			if(StringUtilsV2.isNotBlank(childUserIdsStr)){
				RedisServer.setCacheValue(null, RedisKeyConstant.KEY_USER_IDS_BY_ROLE_IDS+roleIds, childUserIdsStr, expireSeconds);
				return Arrays.asList(childUserIdsStr.split(","));
			}
		}else {
			return Arrays.asList(childUserIds.toString().split(","));
		}
		return null;
	}
	
	public PublicPara setOrgIdAndRoleIds(PublicPara strCon,String permission){
		if(strCon == null){
			strCon = new PublicPara();
		}
		LoginUser loginUser = UserUtil.getLoginUser();
		//不是顶级管理员admin
		if(!Constant.SYSTEM_MANAGE_TOP_USER_IDS.contains(loginUser.getUserId())){
			List<String> permissions = null;
			if(permission != null){
				permissions = permissionDao.childPermissionByUserIdAndPermission(loginUser.getUserId(), permission);
			}
			String orgId = loginUser.getOrgId();
			//org=2默认为平台查询
			//if(Constant.PLATFORM_JKLZ_ORG_ID.equals(loginUser.getOrgId()) && StringUtilsV2.isNotBlank(loginUser.getParentOrgId())) {
			//	orgId = loginUser.getParentOrgId();
			//}
			String childOrgIds = getChildOrgIdsByOrgId(orgId);
			
			strCon.setChildOrgIds(childOrgIds);
			if(permissions != null && permissions.size() == 1 && permissions.get(0).equals(QueryDataType.ONLY.getCode())){
				String roleIds = loginUser.getRoldIds();
				if(StringUtilsV2.isBlank(roleIds)){
					roleIds = roleDao.getRoleIdsByUserId(loginUser.getUserId());
				}
				Object childUserIds = RedisServer.getCacheValue(null,RedisKeyConstant.KEY_CHILD_USER_IDS+roleIds);
				if(childUserIds == null) {
					String childUserIdsStr = userDao.getUserIdsByRoleIds(roleIds);
					if(StringUtilsV2.isNotBlank(childUserIdsStr)) {
						RedisServer.setCacheValue(null, RedisKeyConstant.KEY_CHILD_USER_IDS+roleIds, childUserIdsStr, expireSeconds);
						strCon.setChildUserIds(childUserIdsStr);
					}
				}else {
					strCon.setChildUserIds(childUserIds.toString());
				}
			}
		}
		return strCon;
	}
}
